### Election pledges in multiparty governments: When do voters accept non-fulfillment? ###
### Replication code for the analyses and figures reported in the main text ###

# Please change to your working directory:
setwd("//utuhome.utu.fi/jtylis/pledges-code-and-data")

## LOAD PACKAGES ##

# Data preparation and recoding:
library(readxl)
library(data.table)
library(stats)
library(forcats)
library(fastDummies)

# Variable labels:
library(sjlabelled)

# Linear regression with clustered standard errors ('lm_robust' function):
library(estimatr)

# Plots:
library(sjPlot)
library(ggplot2)
library(cowplot)

# Interaction plots with marginal effects (plot_cme):
library(marginaleffects)

# Results tables:
library(texreg)

## LOAD THE DATASETS ##

# Import the Finnish dataset in 'wide' format:
data_fin_wide <- read_excel("data_fin_wide.xlsx")

# Import the German dataset in 'wide' format:
data_ger_wide <- read_excel("data_ger_wide.xlsx")

# Imported data to "data.tables":
data_fin_wide.dt <- data.table(data_fin_wide)
data_ger_wide.dt <- data.table(data_ger_wide)

## "EQUALRESP" VARIABLES ##

# Before stacking the datasets, create a variable indicating whether 
# a respondent has made the same acceptability evaluation on every round.
# This will be needed in a robustness check (Appendix 5).

# Finnish data:
data_fin_wide.dt$equalresp <- data_fin_wide.dt$outcome_1 == data_fin_wide.dt$outcome_2 &
  data_fin_wide.dt$outcome_2 == data_fin_wide.dt$outcome_3 &
  data_fin_wide.dt$outcome_3 == data_fin_wide.dt$outcome_4 &
  data_fin_wide.dt$outcome_4 == data_fin_wide.dt$outcome_5 &
  data_fin_wide.dt$outcome_5 == data_fin_wide.dt$outcome_6

# German data:
data_ger_wide.dt$equalresp <- data_ger_wide.dt$outcome_1 == data_ger_wide.dt$outcome_2 &
  data_ger_wide.dt$outcome_2 == data_ger_wide.dt$outcome_3 &
  data_ger_wide.dt$outcome_3 == data_ger_wide.dt$outcome_4 &
  data_ger_wide.dt$outcome_4 == data_ger_wide.dt$outcome_5 &
  data_ger_wide.dt$outcome_5 == data_ger_wide.dt$outcome_6

## STACKING THE DATASETS ##

# STACKING THE FINNISH DATASET:

# Recode NA cells to 9999:
data_fin_wide.dt[is.na(data_fin_wide.dt)] <- 9999

# Transform the data into a 'long' i.e. stacked format and name it 'data_fin'
# There should be 2466*6=14796 rows in the new dataset
# Variable 'pledge' (timevar) does not exist yet, running this piece of code will create it:
data_fin <- reshape(data_fin_wide.dt, varying=list(
  opinion = c("opinion_1", "opinion_2", "opinion_3", "opinion_4", "opinion_5", "opinion_6"), 
  importance = c("importance_1", "importance_2", "importance_3", "importance_4", "importance_5", "importance_6"), 
  outcome = c("outcome_1", "outcome_2", "outcome_3", "outcome_4", "outcome_5", "outcome_6"), 
  size = c("size_1", "size_2", "size_3", "size_4", "size_5", "size_6"), 
  position = c("position_1", "position_2", "position_3","position_4", "position_5", "position_6"), 
  program = c("program_1", "program_2", "program_3", "program_4", "program_5", "program_6"), 
  ministry = c("ministry_1", "ministry_2", "ministry_3", "ministry_4", "ministry_5", "ministry_6"), 
  others = c("others_1", "others_2", "others_3", "others_4", "others_5", "others_6"),
  order = c("view_order_Vignette1", "view_order_Vignette2", "view_order_Vignette3", "view_order_Vignette4", "view_order_Vignette5", "view_order_Vignette6")
), 
v.names=c("opinion", "importance", "outcome", "size", "position", "program", "ministry", "others", "order"), 
timevar="pledge", 
times=c(1,2,3,4,5,6), 
idvar="ID",  
direction="long")

# make 9999 cells NAs again:
data_fin_wide.dt[data_fin_wide.dt == 9999] <- NA
data_fin[data_fin == 9999] <- NA

# STACKING THE GERMAN DATASET:

# Recode NA cells to 9999
data_ger_wide.dt[is.na(data_ger_wide.dt)] <- 9999

# Transform the data into a 'long' i.e. stacked format and name it 'data_ger'
# There should be 1359*6=8154 rows in the new dataset
# Variable 'pledge' (timevar) does not exist yet, running this piece of code will create it:
data_ger <- reshape(data_ger_wide.dt, varying=list(
  opinion = c("opinion_1", "opinion_2", "opinion_3", "opinion_4", "opinion_5", "opinion_6"), 
  importance = c("importance_1", "importance_2", "importance_3", "importance_4", "importance_5", "importance_6"), 
  outcome = c("outcome_1", "outcome_2", "outcome_3", "outcome_4", "outcome_5", "outcome_6"), 
  size = c("size_1", "size_2", "size_3", "size_4", "size_5", "size_6"), 
  position = c("position_1", "position_2", "position_3","position_4", "position_5", "position_6"), 
  program = c("program_1", "program_2", "program_3", "program_4", "program_5", "program_6"), 
  ministry = c("ministry_1", "ministry_2", "ministry_3", "ministry_4", "ministry_5", "ministry_6"), 
  others = c("others_1", "others_2", "others_3", "others_4", "others_5", "others_6"),
  order = c("view_order_Vignette1", "view_order_Vignette2", "view_order_Vignette3", "view_order_Vignette4", "view_order_Vignette5", "view_order_Vignette6"),
  importancerank = c("importancerank_1", "importancerank_2", "importancerank_3", "importancerank_4", "importancerank_5","importancerank_6")
  
), 
v.names=c("opinion", "importance", "outcome", "size", "position", "program", "ministry", "others", "order", "importancerank"), 
timevar="pledge", 
times=c(1,2,3,4,5,6), 
idvar="ID",  
direction="long")

# Make 9999 cells NAs again:
data_ger_wide.dt[data_ger_wide.dt == 9999] <- NA
data_ger[data_ger == 9999] <- NA

## VARIABLE RECODING: FINNISH DATA ##

# Opinion variables as factors with value labels in the 'wide' dataset:
data_fin_wide.dt$opinion_1_f <- factor(data_fin_wide.dt$opinion_1, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_fin_wide.dt$opinion_2_f <- factor(data_fin_wide.dt$opinion_2, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_fin_wide.dt$opinion_3_f <- factor(data_fin_wide.dt$opinion_3, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_fin_wide.dt$opinion_4_f <- factor(data_fin_wide.dt$opinion_4, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_fin_wide.dt$opinion_5_f <- factor(data_fin_wide.dt$opinion_5, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FA", "SA", "NAND", "SD", "FD"))
data_fin_wide.dt$opinion_6_f <- factor(data_fin_wide.dt$opinion_6, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))

# Experimental attributes as factors:
data_fin$size_f <- factor(data_fin$size, levels=c(1, 2), 
                          labels=c("Three", "Five"))
data_fin$position_f <- factor(data_fin$position, 
                              levels=c(1, 2, 3), 
                              labels=c("PM", "No_PM", "Small"))
data_fin$program_f <- factor(data_fin$program, 
                             levels=c(1, 2), 
                             labels=c("Included", "Not included"))
data_fin$ministry_f <- factor(data_fin$ministry, 
                              levels=c(1, 2), 
                              labels=c("Yes", "No"))
data_fin$others_f <- factor(data_fin$others, 
                            levels=c(1, 2), 
                            labels=c("Support", "Resist"))

# Give the experimental attributes labels:
data_fin$size_f <- set_label(data_fin$size_f, "Number of parties")
data_fin$position_f <- set_label(data_fin$position_f, "Position")
data_fin$program_f <- set_label(data_fin$program_f, "Coalition agreement")
data_fin$ministry_f <- set_label(data_fin$ministry_f, "Portfolio control")
data_fin$others_f <- set_label(data_fin$others_f, "Other parties")

# Dummy coding of the 'position' variable:
data_fin <- dummy_cols(data_fin, select_columns="position_f")
data_fin$position_f_PM <- set_label(data_fin$position_f_PM, "PM")
data_fin$position_f_NoPM <- set_label(data_fin$`position_f_No_PM`, "No PM")
data_fin$position_f_Small <- set_label(data_fin$position_f_Small, "Small")

# Recode the 'pledge' variable into a labelled factor:
data_fin$pledge_f <- factor(data_fin$pledge, levels=c(1,2,3,4,5,6), 
                            labels=c("Unemployment benefits", "Capital income tax", 
                                     "Cannabis", "Fur farming", "Refugee quota", 
                                     "Gender quotas"))
# Set variable label:
data_fin$pledge_f <- set_label(data_fin$pledge_f, "Pledge")

# Opinion variable as categorical
# Recode 'opinion' into a factor:
data_fin$opinion_f <- factor(data_fin$opinion, levels=c(5,4,3,2,1), 
                             labels=c("Fully disagree", "Somewhat disagree", 
                                      "Neither agree nor disagree", 
                                      "Somewhat agree", "Fully agree"))

# 'opinion' factor with shorter value labels:
data_fin$opinion_f2 <- factor(data_fin$opinion, levels=c(5,4,3,2,1), 
                              labels=c("FD", "SD", "NAND", "SA", "FA"))
data_fin$opinion_f2 <- set_label(data_fin$opinion_f2, "Personal opinion")
# Differentiate those who agree or disagree from those who are neutral:
data_fin$opinion_ext_f <- fct_collapse(data_fin$opinion_f, 
                                       Agree = c("Fully agree", "Somewhat agree"), 
                                       Disagree = c("Somewhat disagree", 
                                                    "Fully disagree"), 
                                       Neutral = c("Neither agree nor disagree"))
# Change the reference category to 'disagree':
data_fin$opinion_ext_f <- factor(data_fin$opinion_ext_f, 
                                 levels=c("Disagree", "Neutral", "Agree"))
# Set variable label:
data_fin$opinion_ext_f <- set_label(data_fin$opinion_ext_f, "Personal opinion")

# Left-right and liberal-conservative self-placements: recode 'don't knows' (11) to missing:
data_fin$leftright[data_fin$leftright==11] <- NA
data_fin$libcons[data_fin$libcons==11] <- NA
# Set variable labels:
data_fin$leftright <- set_label(data_fin$leftright, "Left-right")
data_fin$libcons <- set_label(data_fin$libcons, "Liberal-conservative")

# Government supporter dummy
data_fin$voteintention_f <- factor(data_fin$voteintention,
                                    levels=c(1,2,3,4,5,6,7,8,9,10,11,12,13),
                                    labels=c(
                                      "KOK", "PS", "SDP", "KESK", "VIHR", "VAS", "RKP",
                                      "KD", "LIIK", "Other",
                                      "Would not vote", "Cannot say", "Prefer not to disclose"
                                    ))
data_fin$governmentsupporter_f <- fct_collapse(data_fin$voteintention_f, 
                                               Government=c(
                                                 "KOK", "PS", "RKP", "KD"
                                               ), 
                                               Other=c(
                                                 "SDP", "KESK", "VIHR", "VAS", "LIIK",
                                                 "Other", "Would not vote", "Cannot say",
                                                 "Prefer not to disclose")
)

data_fin <- dummy_cols(data_fin, select_columns="governmentsupporter_f")
data_fin$governmentsupporter_f_Government <- set_label(data_fin$governmentsupporter_f_Government, 
                                                       "Government supporter")

# Education: factor with three levels:
data_fin$edu3_f <- factor(data_fin$edu3,
                          levels=c(1,2,3),
                          labels=c("Primary", "Secondary", "Tertiary"))
data_fin$edu3_f <- set_label(data_fin$edu3_f, "Education")

# Gender: differentiate those identifying as female from the rest:
data_fin$gender_f <- factor(data_fin$gender,
                            levels=c(1,2,3),
                            labels=c("Male", "Female", "Other/prefer not to disclose"))
data_fin$female_f <- fct_collapse(data_fin$gender_f,
                                  Female=c("Female"),
                                  Not_female=c("Male", "Other/prefer not to disclose"))
# Set 'not female' as reference category:
data_fin$female_f <- factor(data_fin$female_f,
                            levels=c("Not_female", "Female"))
# Set variable label:
data_fin$female_f <- set_label(data_fin$female_f, "Gender")

# Age group: factor with four levels:
data_fin$agegroup4_f <- factor(data_fin$agegroup4,
                               levels=c(1,2,3,4),
                               labels=c("18-34", "35-49", "50-64", "65+"))
# Set variable label:
data_fin$agegroup4_f <- set_label(data_fin$agegroup4_f, "Age")

# Vignette order factor:
data_fin$order_f <- factor(data_fin$order,
                           levels=c(1,2,3,4,5,6),
                           labels=c("1","2","3","4","5","6"))
data_fin$order_f <- set_label(data_fin$order_f, "Vignette")

# "Equal responses" as a factor:
data_fin$equalresp_f <- factor(data_fin$equalresp)

## VARIABLE RECODING: GERMAN DATA ##

# Opinion variables as factors with value labels in the 'wide' dataset:
data_ger_wide.dt$opinion_1_f <- factor(data_ger_wide.dt$opinion_1, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_ger_wide.dt$opinion_2_f <- factor(data_ger_wide.dt$opinion_2, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_ger_wide.dt$opinion_3_f <- factor(data_ger_wide.dt$opinion_3, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_ger_wide.dt$opinion_4_f <- factor(data_ger_wide.dt$opinion_4, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_ger_wide.dt$opinion_5_f <- factor(data_ger_wide.dt$opinion_5, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))
data_ger_wide.dt$opinion_6_f <- factor(data_ger_wide.dt$opinion_6, 
                                       levels=c(5,4,3,2,1), 
                                       labels=c("FD", "SD", "NAND", "SA", "FA"))

# Experimental attributes as factors:
data_ger$size_f <- factor(data_ger$size, levels=c(1,2), 
                          labels=c("Two", "Three"))
data_ger$position_f <- factor(data_ger$position, 
                              levels=c(1,2), 
                              labels=c("PM", "No_PM"))
data_ger$program_f <- factor(data_ger$program, 
                             levels=c(1,2), 
                             labels=c("Included", "Not included"))
data_ger$ministry_f <- factor(data_ger$ministry, 
                              levels=c(1,2), 
                              labels=c("Yes", "No"))
data_ger$others_f <- factor(data_ger$others, 
                            levels=c(1,2), 
                            labels=c("Support", "Resist"))

# Give the experimental attributes variable labels:
data_ger$size_f <- set_label(data_ger$size_f, "Number of parties")
data_ger$position_f <- set_label(data_ger$position_f, "Position")
data_ger$program_f <- set_label(data_ger$program_f, "Coalition agreement")
data_ger$ministry_f <- set_label(data_ger$ministry_f, "Portfolio control")
data_ger$others_f <- set_label(data_ger$others_f, "Other parties")

# Recode the 'pledge' variable into a labelled factor:
data_ger$pledge_f <- factor(data_ger$pledge, levels=c(1,2,3,4,5,6), 
                            labels=c("Military service", "Unemployment benefits", 
                                     "Speed limit", "Debt brake", 
                                     "Number of refugees", "Gender quotas"))
# Change the reference category --> the coefficients on the other pledges become positive:
data_ger$pledge_f1 <- factor(data_ger$pledge, levels=c(5,1,2,3,4,6), 
                             labels=c("Number of refugees", "Military service", 
                                      "Unemployment benefits", "Speed limit", 
                                      "Debt brake", "Gender quotas"))
# set variable label:
data_ger$pledge_f1 <- set_label(data_ger$pledge_f1, "Pledge")

# Opinion variable as categorical
# Recode 'opinion' into a factor ending with _f:
data_ger$opinion_f <- factor(data_ger$opinion, levels=c(5,4,3,2,1), 
                             labels=c("Fully disagree", "Somewhat disagree", 
                                      "Neither agree nor disagree", 
                                      "Somewhat agree", "Fully agree"))
# 'opinion' factor with somewhat shorter value labels:
data_ger$opinion_f2 <- factor(data_ger$opinion, levels=c(5,4,3,2,1), 
                              labels=c("FD", "SD", "NAND", "SA", "FA"))
data_ger$opinion_f2 <- set_label(data_ger$opinion_f2, "Personal opinion")
# Differentiate those who agree or disagree from those who are neutral:
data_ger$opinion_ext_f <- fct_collapse(data_ger$opinion_f, 
                                       Agree = c("Fully agree", "Somewhat agree"), 
                                       Disagree = c("Somewhat disagree", 
                                                    "Fully disagree"), 
                                       Neutral = c("Neither agree nor disagree"))
# Change the reference category to 'disagree':
data_ger$opinion_ext_f <- factor(data_ger$opinion_ext_f, 
                                 levels=c("Disagree", "Neutral", "Agree"))
# Set variable label:
data_ger$opinion_ext_f <- set_label(data_ger$opinion_ext_f, "Personal opinion")

# Ranked issue importance as a factor:
data_ger$importancerank_f <- factor(data_ger$importancerank, levels=c(1,2,3,4,5,6), 
                                    labels=c("1st", "2nd", 
                                             "3rd", "4th", 
                                             "5th", "6th"))

# Party preference
# Government supporter dummy:
data_ger$voteintention_f <- factor(data_ger$voteintention, levels=c(1,2,3,4,5,6,7,8,9,10,11), 
                                   labels=c("SPD", "CDU/CSU", "B90/DG", "FDP", "AFD", 
                                            "The Left", "Free Voters", "BSW", "Other", 
                                            "Don't know", "Wouldn't vote"))
data_ger$governmentsupporter_f <- fct_collapse(data_ger$voteintention_f, 
                                               Government=c("SPD", "B90/DG", "FDP"), 
                                               Other=c("CDU/CSU",  "AFD", "The Left", 
                                                       "Free Voters", "BSW", "Other", 
                                                       "Don't know", "Wouldn't vote"))
data_ger <- dummy_cols(data_ger, select_columns="governmentsupporter_f")
data_ger$governmentvoter_f_Government <- set_label(data_ger$governmentsupporter_f_Government, 
                                                   "Government supporter")

# Education: factor with three levels:
data_ger$edu3_f <- factor(data_ger$edu3,
                          levels=c(1,2,3),
                          labels=c("Primary", "Secondary", "Tertiary"))
data_ger$edu3_f <- set_label(data_ger$edu3_f, "Education")

# Gender: differentiate those identifying as female from the rest:
data_ger$gender_f <- factor(data_ger$gender,
                            levels=c(1,2,3),
                            labels=c("Male", "Female", "Other/prefer not to disclose"))
data_ger$female_f <- fct_collapse(data_ger$gender_f,
                                  Female=c("Female"),
                                  Not_female=c("Male", "Other/prefer not to disclose"))
# Set 'not female' as reference category:
data_ger$female_f <- factor(data_ger$female_f,
                            levels=c("Not_female", "Female"))
# Set variable label:
data_ger$female_f <- set_label(data_ger$female_f, "Gender")

# Age group: factor with four levels:
data_ger$agegroup4_f <- factor(data_ger$agegroup4,
                               levels=c(1,2,3,4),
                               labels=c("18-34", "35-49", "50-64", "65+"))
# Set variable label:
data_ger$agegroup4_f <- set_label(data_ger$agegroup4_f, "Age")

# Vignette order factor:
data_ger$order_f <- factor(data_ger$order,
                           levels=c(1,2,3,4,5,6),
                           labels=c("1","2","3","4","5","6"))
data_ger$order_f <- set_label(data_ger$order_f, "Vignette")

# "Equal responses" as a factor:
data_ger$equalresp_f <- factor(data_ger$equalresp)

## FIGURE 1: Distribution of opinions about policy statements in Finland ##

# Filter out non-citizens:
data_fin_wide.dt <- subset(data_fin_wide.dt, citizenship==1)

# Bar charts showing the relative frequencies as percentages:
opinion_1_f_bar <- ggplot(data_fin_wide.dt, aes(x=opinion_1_f), 
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Unemployment benefits") + theme(plot.title=element_text(size=10))
opinion_2_f_bar <- ggplot(data_fin_wide.dt, aes(x=opinion_2_f), 
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Capital income tax") + theme(plot.title=element_text(size=10))
opinion_3_f_bar <- ggplot(data_fin_wide.dt, aes(x=opinion_3_f),
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Cannabis") + theme(plot.title=element_text(size=10))
opinion_4_f_bar <- ggplot(data_fin_wide.dt, aes(x=opinion_4_f),
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Fur farming") + theme(plot.title=element_text(size=10))
opinion_5_f_bar <- ggplot(data_fin_wide.dt, aes(x=opinion_5_f),
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Refugee quota") + theme(plot.title=element_text(size=10))
opinion_6_f_bar <- ggplot(data_fin_wide.dt, aes(x=opinion_6_f),
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Gender quotas") + theme(plot.title=element_text(size=10))

# Arrange the bar charts into a grid:
opinion_fi_grid <- plot_grid(opinion_1_f_bar, opinion_2_f_bar, opinion_3_f_bar, 
                             opinion_4_f_bar, opinion_5_f_bar, opinion_6_f_bar)

# Print the plot grid:
print(opinion_fi_grid)

## FIGURE 2: Distribution of opinions about policy statements in Germany ##

# Bar charts showing the relative frequencies as percentages:
opinion_1_f_bar <- ggplot(data_ger_wide.dt, aes(x=opinion_1_f), 
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Military service") + theme(plot.title=element_text(size=10))
opinion_2_f_bar <- ggplot(data_ger_wide.dt, aes(x=opinion_2_f), 
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Unemployment benefits") + theme(plot.title=element_text(size=10))
opinion_3_f_bar <- ggplot(data_ger_wide.dt, aes(x=opinion_3_f), 
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Speed limit") + theme(plot.title=element_text(size=10))
opinion_4_f_bar <- ggplot(data_ger_wide.dt, aes(x=opinion_4_f), 
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Debt brake") + theme(plot.title=element_text(size=10))
opinion_5_f_bar <- ggplot(data_ger_wide.dt, aes(x=opinion_5_f), 
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Number of refugees") + theme(plot.title=element_text(size=10))
opinion_6_f_bar <- ggplot(data_ger_wide.dt, aes(x=opinion_6_f), 
                          na.rm=TRUE, color="black", fill="grey") + geom_bar(aes(y=(..count..)/sum(..count..)), width=0.7) + theme_classic() + scale_x_discrete(limits=c("FD", "SD", "NAND", "SA", "FA")) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.5)) + labs(x="", y="", title="Gender quotas") + theme(plot.title=element_text(size=10))

# Arrange the bar charts into a grid:
opinion_de_grid <- plot_grid(opinion_1_f_bar, opinion_2_f_bar, 
                             opinion_3_f_bar, opinion_4_f_bar, 
                             opinion_5_f_bar, opinion_6_f_bar)

# Print the plot grid:
print(opinion_de_grid)

## MEAN AND STANDARD DEVIATION OF THE OUTCOME VARIABLE ##

# Finland:
mean(data_fin$outcome, na.rm = T) # Mean
sd(data_fin$outcome, na.rm = T) # Standard deviation

# Germany:
mean(data_ger$outcome, na.rm = T) # Mean
sd(data_ger$outcome, na.rm = T) # Standard deviation

## FIGURE 3: Distribution of the outcome variable: Acceptability evaluation ##

# Filter out non-citizens from the Finnish data:
data_fin <- subset(data_fin, citizenship==1)

# Distribution in the Finnish dataset:
outcome_hist_fi <- ggplot(
  data_fin, aes(x=outcome)) + geom_histogram(binwidth=1,
                                             color="black",
                                             fill="grey",
                                             aes(y=after_stat(count/sum(count)))) + scale_x_continuous(breaks=c(0,1,2,3,4,5,6,7,8,9,10)) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.25)) + labs(title="Finland", x="Outcome", y="") + theme_classic() + theme(plot.title=element_text(size=10)) + theme(axis.title.x = element_text(size=10))

# Distribution in the German dataset:
outcome_hist_ger <- ggplot(
  data_ger, aes(x=outcome)) + geom_histogram(binwidth=1,
                                             color="black",
                                             fill="grey",
                                             aes(y=after_stat(count/sum(count)))) + scale_x_continuous(breaks=c(0,1,2,3,4,5,6,7,8,9,10)) + scale_y_continuous(labels=scales::percent, limits=c(0, 0.25))  + labs(title="Germany", x="Outcome", y="") + theme_classic() + theme(plot.title=element_text(size=10)) + theme(axis.title.x = element_text(size=10))

# Arrange the histograms into a grid:
outcome_hist_fi_ger <- plot_grid(outcome_hist_fi, outcome_hist_ger)

# Print the grid:
print(outcome_hist_fi_ger)

## REGRESSION MODELS ##

# ADDITIVE MODELS

# Regression model with clustered standard errors, Finland:
model01_fin <- lm_robust(outcome ~ size_f + position_f + program_f
                         + ministry_f + others_f + opinion_ext_f
                         + pledge_f + order_f,
                         data=data_fin, clusters=ID, se_type="stata")
summary(model01_fin)

# Test the difference between small size and no PM:
hypotheses(model01_fin, "position_fSmall = position_fNo_PM")

# Results as Latex table (Table S5 in Supplementary Material):
texreg(model01_fin, digits=3,
       caption="Regression results: Finland",
       caption.above=TRUE,
       include.ci=FALSE,
       single.row=TRUE,
       custom.model.names="Beta (clust. SE)",
       custom.coef.names = c("Intercept",
                             "Number of parties: Five",
                             "Party status: Large, no PM",
                             "Party size: Small",
                             "Coalition agreement: Not included",
                             "Portfolio control: No",
                             "Other parties: Resist",
                             "Opinion: Neutral",
                             "Opinion: Agree",
                             "Pledge: Capital income tax",
                             "Pledge: Cannabis",
                             "Pledge: Fur farming",
                             "Pledge: Refugee quota",
                             "Pledge: Gender quotas",
                             "Vignette 2",
                             "Vignette 3",
                             "Vignette 4",
                             "Vignette 5",
                             "Vignette 6"),
       reorder.coef=c(1,2,4,7,3,6,5,8,9,10,11,12,13,14,15,16,17,18,19))

# Regression model with clustered standard errors, Germany:
model01_ger <- lm_robust(outcome ~ size_f + position_f + program_f
                         + ministry_f + others_f + opinion_ext_f
                         + pledge_f1 + order_f,
                         data=data_ger, clusters=ID, se_type="stata")
summary(model01_ger)

# Results as Latex table (Table S6 in Supplementary Material):
texreg(model01_ger, digits=3,
       caption="Regression results: Germany",
       caption.above=TRUE,
       include.ci=FALSE,
       single.row=TRUE,
       custom.model.names="Beta (clust. SE)",
       custom.coef.names = c("Intercept", "Number of parties: Three", 
                             "Party status: Junior partner",
                             "Coalition agreement: Not included",
                             "Portfolio control: No",
                             "Other parties: Resist",
                             "Opinion: Neutral",
                             "Opinion: Agree",
                             "Pledge: Military service",
                             "Pledge: Unemployment benefits",
                             "Pledge: Speed limit",
                             "Pledge: Debt brake",
                             "Pledge: Gender quotas",
                             "Vignette 2",
                             "Vignette 3",
                             "Vignette 4",
                             "Vignette 5",
                             "Vignette 6"),
       reorder.coef=c(1,2,6,3,5,4,7,8,9,10,11,12,13,14,15,16,17,18))

# INTERACTION MODELS

# Finland (use the dummy coded 'position_f' variable):
model02_fin <- lm_robust(outcome ~ opinion_ext_f * size_f +
                           opinion_ext_f * position_f_NoPM +
                           opinion_ext_f * position_f_Small +
                           opinion_ext_f * program_f +
                           opinion_ext_f * ministry_f +
                           opinion_ext_f * others_f +
                           pledge_f + order_f,
                         data=data_fin, clusters=ID, se_type="stata")
summary(model02_fin)

# Results as Latex table (Table S7 in Supplementary Material):
texreg(model02_fin, digits=3, 
       caption="Regression results including interactions: Finland", 
       caption.above=TRUE,
       include.ci=FALSE,
       single.row=TRUE,
       custom.model.names="Beta (clust. SE)",
       custom.coef.names = c("Intercept",
                             "Personal opinion: Neutral",
                             "Personal opinion: Agree",
                             "Number of parties: Five",
                             "Party status: Large, no PM",
                             "Party size: Small",
                             "Coalition agreement: Not included",
                             "Ministerial portfolio: No",
                             "Other parties: Resist",
                             "Pledge: Capital income tax",
                             "Pledge: Cannabis",
                             "Pledge: Fur farming",
                             "Pledge: Refugee quota",
                             "Pledge: Gender quotas",
                             "Vignette 2",
                             "Vignette 3",
                             "Vignette 4",
                             "Vignette 5",
                             "Vignette 6",
                             "Number of parties: Five * Opinion: Neutral",
                             "Number of parties: Five * Opinion: Agree",
                             "Party status: Large, no PM * Opinion: Neutral",
                             "Party status: Large, no PM * Opinion: Agree",
                             "Party size: Small * Opinion: Neutral",
                             "Party size: Small * Opinion: Agree",
                             "Coalition agreement: Not included * Opinion: Neutral",
                             "Coalition agreement: Not included * Opinion: Agree",
                             "Ministerial portfolio: No * Opinion: Neutral",
                             "Ministerial portfolio: No * Opinion: Agree",
                             "Other parties: Resist * Opinion: Neutral",
                             "Other parties: Resist * Opinion: Agree"),
       reorder.coef=c(1,4,6,9,5,8,7,2,3,20,21,24,25,30,31,22,23,28,29,26,27,10,11,12,13,14,15,16,17,18,19))

# Germany:
model02_ger <- lm_robust(outcome ~ opinion_ext_f * size_f +
                           opinion_ext_f * position_f +
                           opinion_ext_f * program_f +
                           opinion_ext_f * ministry_f +
                           opinion_ext_f * others_f +
                           pledge_f1 + order_f,
                         data=data_ger, clusters=ID, se_type="stata")
summary(model02_ger)

# Results as Latex table (Table S8 in Supplementary Material):
texreg(model02_ger, digits=3, 
       caption="Regression results including interactions: Germany", 
       caption.above=TRUE,
       include.ci=FALSE,
       single.row=TRUE,
       custom.model.names="Beta (clust. SE)",
       custom.coef.names = c("Intercept",
                             "Personal opinion: Neutral",
                             "Personal opinion: Agree",
                             "Number of parties: Three",
                             "Party status: Junior partner",
                             "Coalition agreement: Not included",
                             "Ministerial portfolio: No",
                             "Other parties: Resist",
                             "Pledge: Military service",
                             "Pledge: Unemployment benefits",
                             "Pledge: Speed limit",
                             "Pledge: Debt brake",
                             "Pledge: Gender quotas",
                             "Vignette 2",
                             "Vignette 3",
                             "Vignette 4",
                             "Vignette 5",
                             "Vignette 6",
                             "Number of parties: Three * Opinion: Neutral",
                             "Number of parties: Three * Opinion: Agree",
                             "Party status: Junior partner * Opinion: Neutral",
                             "Party status: Junior partner * Opinion: Agree",
                             "Coalition agreement: Not included * Opinion: Neutral",
                             "Coalition agreement: Not included * Opinion: Agree",
                             "Ministerial portfolio: No * Opinion: Neutral",
                             "Ministerial portfolio: No * Opinion: Agree",
                             "Other parties: Resist * Opinion: Neutral",
                             "Other parties: Resist * Opinion: Agree"),
       reorder.coef=c(1,4,8,5,7,6,2,3,19,20,27,28,21,22,25,26,23,24,9,10,11,12,13,14,15,16,17,18))

# FIGURE 4: Regression results: Explaining acceptability of non-fulfillment

# Plot the results of model01_fin:
twowayfe_plot_fin <- plot_model(model01_fin, prefix.labels="label", 
                                show.legend=FALSE, show.p=TRUE, show.values=TRUE, 
                                value.offset=.4, value.size=3, 
                                rm.terms=c("pledge_fCapital income tax", 
                                           "pledge_fCannabis", 
                                           "pledge_fFur farming", 
                                           "pledge_fRefugee quota", 
                                           "pledge_fGender quotas", 
                                           "order_f2", 
                                           "order_f3", 
                                           "order_f4", 
                                           "order_f5", 
                                           "order_f6"), 
                                colors="bw", vline.color="grey") + labs(title="Finland") + theme_sjplot2()

# Plot the results of model01_ger:
twowayfe_plot_ger <- plot_model(model01_ger, prefix.labels="label", 
                                show.legend=FALSE, show.p=TRUE, show.values=TRUE, 
                                value.offset=.4, value.size=3, 
                                rm.terms=c("pledge_f1Military service", 
                                           "pledge_f1Unemployment benefits", 
                                           "pledge_f1Speed limit", 
                                           "pledge_f1Debt brake", 
                                           "pledge_f1Gender quotas", 
                                           "order_f2", 
                                           "order_f3", 
                                           "order_f4", 
                                           "order_f5", 
                                           "order_f6"), 
                                colors="bw", vline.color="grey") + labs(title="Germany") + theme_sjplot2()

# Combine the plots into a grid:
addmodelsplot <- plot_models(model01_ger, model01_fin,
                             prefix.labels="label",
                             show.p=TRUE,
                             show.values=TRUE,
                             m.labels=c("Germany", "Finland"),
                             show.legend=FALSE,
                             colors="bw",
                             vline.color="grey",
                             grid=TRUE,
                             value.size=3.5,
                             dot.size=2.5,
                             rm.terms=c(
                               "pledge_fCapital income tax", 
                               "pledge_fCannabis", 
                               "pledge_fFur farming", 
                               "pledge_fRefugee quota", 
                               "pledge_fGender quotas",
                               "pledge_f1Military service", 
                               "pledge_f1Unemployment benefits", 
                               "pledge_f1Speed limit", 
                               "pledge_f1Debt brake", 
                               "pledge_f1Gender quotas", 
                               "order_f2", 
                               "order_f3", 
                               "order_f4", 
                               "order_f5", 
                               "order_f6"
                             )) + theme_sjplot2()

# Transform the data of the combined plot to rearrange the coefficients and exclude the fixed effects:
addmodelsplot$data <- transform(addmodelsplot$data, 
                                term = factor(term, levels = c("opinion_ext_fAgree",
                                                               "opinion_ext_fNeutral",
                                                               "program_fNot included",
                                                               "ministry_fNo",
                                                               "position_fJunior partner",
                                                               "position_fNo_PM",
                                                               "others_fResist",
                                                               "position_fSmall",
                                                               "size_fThree",
                                                               "size_fFive"),
                                              labels=c("Personal opinion: Agree",
                                                       "Personal opinion: Neutral",
                                                       "Not included\n in coalition agreement",
                                                       "No portfolio control",
                                                       "Party status: Junior partner",
                                                       "Party status: Large, no PM",
                                                       "Disagreement\n in government",
                                                       "Party size: Small",
                                                       "Number of parties: Three",
                                                       "Number of parties: Five"
                                              )))
# Print the transformed plot (Figure 4):
print(addmodelsplot)

## FIGURE 5: Marginal effects of the attribute levels in Finland ##

# Plot the conditional marginal effects of experimental attributes:
model02_fin.cme1 <- plot_slopes(model02_fin, variables="size_f", condition="opinion_ext_f", draw=TRUE
) + labs(y="Marginal effect", x="", title="Number of parties: Five"
) + ylim(-0.2, 1.5) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_fin.cme2 <- plot_slopes(model02_fin, variables="position_f_NoPM", condition="opinion_ext_f", draw=TRUE
) + labs(y="", x="", title="Party status: Large, no PM"
) + ylim(-0.2, 1.5) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_fin.cme2b <- plot_slopes(model02_fin, variables="position_f_Small", condition="opinion_ext_f", draw=TRUE
) + labs(y="", x="", title="Party size: Small"
) + ylim(-0.2, 1.5) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_fin.cme3 <- plot_slopes(model02_fin, variables="program_f", condition="opinion_ext_f", draw=TRUE
) + labs(y="", x="Personal opinion", title="Not included in coalition agreement"
) + ylim(-0.2, 1.5) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_fin.cme4 <- plot_slopes(model02_fin, variables="ministry_f", condition="opinion_ext_f", draw=TRUE
) + labs(y="Marginal effect", x="Personal opinion", title="No portfolio control"
) + ylim(-0.2, 1.5) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_fin.cme5 <- plot_slopes(model02_fin, variables="others_f", condition="opinion_ext_f", draw=TRUE
) + labs(y="Marginal effect", x="", title="Disagreement in government"
) + ylim(-0.2, 1.5) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))

# Combine into a grid:
marginaleffectgrid_fin <- plot_grid(model02_fin.cme1, model02_fin.cme2b,
                                    model02_fin.cme5, model02_fin.cme2,
                                    model02_fin.cme4, model02_fin.cme3, ncol=2)

# Print the grid (Figure 5):
print(marginaleffectgrid_fin)

## FIGURE 6: Marginal effects of the attribute levels in Germany ##

# Plot the conditional marginal effects of experimental attributes:
model02_ger.cme1 <- plot_slopes(model02_ger, variables="size_f",condition="opinion_ext_f", draw=TRUE
) + labs(y="Marginal effect", x="", title="Number of parties: Three"
) + ylim(-0.4, 1.0) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_ger.cme2 <- plot_slopes(model02_ger, variables="position_f", condition="opinion_ext_f", draw=TRUE
) + labs(y="Marginal effect", x="", title="Party status: Junior partner"
) + ylim(-0.4, 1.0) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_ger.cme3 <- plot_slopes(model02_ger, variables="program_f", condition="opinion_ext_f", draw=TRUE
) + labs(y="Marginal effect", x="Personal opinion", title="Not included in coalition agreement"
) + ylim(-0.4, 1.0) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_ger.cme4 <- plot_slopes(model02_ger, variables="ministry_f", condition="opinion_ext_f", draw=TRUE
) + labs(y="", x="Personal opinion", title="No portfolio control"
) + ylim(-0.4, 1.0) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))
model02_ger.cme5 <- plot_slopes(model02_ger, variables="others_f", condition="opinion_ext_f", draw=TRUE
) + labs(y="", x="", title="Disagreement in government"
) + ylim(-0.4, 1.0) + theme_light() + theme(axis.title=element_text(size=10), plot.title=element_text(size=10, face="bold"))

# Combine into a grid:
marginaleffectgrid_ger <- plot_grid(model02_ger.cme1, model02_ger.cme5,
                                    model02_ger.cme2, model02_ger.cme4,
                                    model02_ger.cme3, ncol=2)

# Print the grid (Figure 6):
print(marginaleffectgrid_ger)
